package pl.com.like.sequoia.web.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import pl.com.like.sequoia.annotations.Nullable;
import pl.com.like.sequoia.dao.admin.IUploadedFileDao;
import pl.com.like.sequoia.exceptions.LogicalException;
import pl.com.like.sequoia.exceptions.TechnicalException;
import pl.com.like.sequoia.jms.client.producer.IJmsMessageProducer;
import pl.com.like.sequoia.model.admin.UploadedFile;
import pl.com.like.sequoia.model.security.User;
import pl.com.like.sequoia.service.IConfigService;
import pl.com.like.sequoia.web.vo.UpFile;

public class UploadHelperService implements IUploadHelperService {

	private final Logger log = LoggerFactory.getLogger(UploadHelperService.class);

	@Autowired
	private IConfigService configService;
	@Autowired
	private IUserService userService;
	@Autowired
	private IUploadedFileDao uploadedFileDao;
	@Autowired
	private IJmsMessageProducer messageProducer;

	/**
	 * Generate new temporary directory for uploaded file.
	 */
	public File getUploadDir() {
		long now = System.currentTimeMillis();
		String nowStr = new Long(now).toString();
		MessageDigest m;
		String newDirName = nowStr;
		try {
			m = MessageDigest.getInstance("MD5");
			m.update(nowStr.getBytes(), 0, nowStr.length());
			newDirName = new BigInteger(1, m.digest()).toString(16);
		} catch (NoSuchAlgorithmException e) {
			log.warn("could not generate md5 from date.");
		}
		java.io.File uploadDir = new java.io.File(configService.getUploadPath());
		java.io.File newUplDir = new java.io.File(uploadDir, newDirName);
		newUplDir.mkdirs();
		return newUplDir;
	}

	/** {@inheritDoc} */
	@Nullable
	public String getUploadPath() {
		String uploadDir = null;
		try {
			if (log.isDebugEnabled()) {
				log.debug("trying to get upload folder");
			}
			uploadDir = configService.getUploadPath();
		} catch (LogicalException e) {
			log.error("could not get upload folder from application settings", e);
		}
		return uploadDir;
	}

	public void saveFacesUploadedInfo(UpFile uploadedFile, String username) {
		Assert.notNull(uploadedFile);
		File savedFile = saveFile(uploadedFile);
		Date currDate = Calendar.getInstance(TimeZone.getDefault()).getTime();
		UploadedFile upFile = new UploadedFile();
		upFile.setUploadDate(currDate);
		upFile.setScanned(Boolean.FALSE);
		upFile.setPath(savedFile.getAbsolutePath());
		if (username != null) {
			User user = userService.getUser(username, null);
			if (user != null) {
				upFile.setOwner(user);
			}
		}
		uploadedFileDao.saveOrUpdate(upFile);
		if (log.isDebugEnabled()) {
			log.debug("sending jms message about new uploaded file {}", upFile.getPath());
		}
		messageProducer.triggerFileScanning(upFile.getId());
	}

	public java.io.File saveFile(UpFile upFile) {
		java.io.File uploadDir = getUploadDir();
		java.io.File savedFile;
		try {
			savedFile = new java.io.File(uploadDir, upFile.getName());
			FileOutputStream fos = new FileOutputStream(savedFile);
			fos.write(upFile.getData());
			fos.close();
		} catch (IOException e) {
			throw new TechnicalException("could not create temporary file for downloads.");
		}

		return savedFile;
	}

	public void saveUploadedInfo(java.io.File uploadedFile, String username) {
		Assert.notNull(uploadedFile);
		Date currDate = Calendar.getInstance(TimeZone.getDefault()).getTime();
		UploadedFile upFile = new UploadedFile();
		upFile.setUploadDate(currDate);
		upFile.setScanned(Boolean.FALSE);
		upFile.setPath(uploadedFile.getAbsolutePath());
		if (username != null) {
			User user = userService.getUser(username, null);
			if (user != null) {
				upFile.setOwner(user);
			}
		}
		uploadedFileDao.saveOrUpdate(upFile);
		if (log.isDebugEnabled()) {
			log.debug("sending jms message about new uploaded file {}", upFile.getPath());
		}
		messageProducer.triggerFileScanning(upFile.getId());
	}
}
